/*****************************************************************************
 *                                                                           *
 * Module:       Altera_UP_Pixel_Buffer                                      *
 * Description:                                                              *
 *      This module enables reads and writes to the sram, for the vga buffer *
 *   with backbuffer at the screen resolutions of 320x240 through 80x60      *
 *   (16-bit colour), and without backbuffer at the screen resolutions of    *
 *   640x480 (8-bit colour).                                                 *
 *                                                                           *
 *****************************************************************************/


module Altera_UP_Pixel_Buffer (
	// Inputs
	clk,
	clk_for_vga,
	reset,

	colour_in,
	x_position_in,
	y_position_in,
	write_pixel_en,
	frame_complete_request,
	
//	grid_colour_in,

	line_counter,
	pixel_counter,
	end_of_frame,

//	vga_ctlr_address,
//	vga_ctlr_read,

	// Bi-Directional
	SRAM_DQ,

	// Outputs
	SRAM_ADDR,
	SRAM_LB_N,
	SRAM_UB_N,
	SRAM_CE_N,
	SRAM_OE_N,
	SRAM_WE_N,

//	vga_ctlr_read_data

	frame_complete_ack,
	
	data_to_system,
	data_to_vga
);


/*****************************************************************************
 *                           Parameter Declarations                          *
 *****************************************************************************/

parameter NUMBER_OF_BITS_FOR_LINES			= 10;
parameter NUMBER_OF_BITS_FOR_PIXELS			= 10;
parameter NUMBER_OF_BITS_FOR_VGA_ADDRESS	= 19;

/*****************************************************************************
 *                             Port Declarations                             *
 *****************************************************************************/
// Inputs
input				clk;
input				clk_for_vga;
input				reset;

input		[15:0]	colour_in;
input		[6:0]	x_position_in;
input		[5:0]	y_position_in;
input				write_pixel_en;
input				frame_complete_request;

//input		[14:0]	grid_colour_in;

input 		[8:0]	line_counter;
input 		[9:0]	pixel_counter;
input				end_of_frame;

//input 		[(NUMBER_OF_BITS_FOR_VGA_ADDRESS-1):0]	vga_ctlr_address;
//input				vga_ctlr_read;

// Bi-Directional
inout		[15:0]	SRAM_DQ;

// Outputs
output		[17:0]	SRAM_ADDR;
output				SRAM_LB_N;
output				SRAM_UB_N;
output				SRAM_CE_N;
output				SRAM_OE_N;
output				SRAM_WE_N;

output	reg			frame_complete_ack;

output	reg	[15:0]	data_to_system;
output	reg	[15:0]	data_to_vga;
//output	reg	[31:0]	vga_ctlr_read_data;

/*****************************************************************************
 *                           Constant Declarations                           *
 *****************************************************************************/

localparam	PL = 2; // Pipeline Length

/*****************************************************************************
 *                 Internal Wires and Registers Declarations                 *
 *****************************************************************************/
// Internal Wires
wire		[17:0]	address_for_sram;
wire		[15:0]	data_from_sram;

// Internal Registers
reg					sram_access;
reg					frame_access;
reg			[15:0]	delay_data_to_vga [PL:1];

reg					read_switch_info;
// State Machine Registers
// temps
/*
wire		[15:0]	colour_in;
wire		[6:0]	x_position_in;
wire		[5:0]	y_position_in;
wire				write_pixel_en;
wire				frame_complete_request;

wire		[14:0]	grid_colour_in;

wire 		[8:0]	line_counter;
wire 		[9:0]	pixel_counter;
wire				end_of_frame;
reg			[15:0]	data_to_system;
reg					frame_complete_ack;
*/

// Integers
integer				i;

/*****************************************************************************
 *                            Output assignments                             *
 *****************************************************************************/

assign address_for_sram[17]		= 1'b0; // (sram_access ^ frame_access);
assign address_for_sram[16:0]	= (sram_access == 1'b1) ? 
//			17'h00000 : vga_ctlr_address;
			//{vga_ctlr_address[18:11], vga_ctlr_address[9:1]};
			{4'h0,y_position_in,x_position_in} :
			{4'h0,line_counter[8:3],pixel_counter[9:3]};


/*****************************************************************************
 *                         Finite State Machine(s)                           *
 *****************************************************************************/


/*****************************************************************************
 *                             Sequential logic                              *
 *****************************************************************************/

always @(posedge clk)
begin
	if (reset == 1'b1)
	begin
		sram_access <= 1'b0;
	end
	else
	begin
		sram_access <= sram_access ^ 1'b1;
	end
end

always @(posedge clk)
begin
	if (reset == 1'b1)
	begin
		frame_access <= 1'b0;
	end
	else if ((end_of_frame == 1'b1) &&
			(frame_complete_request == 1'b1) &&
			(frame_complete_ack == 1'b0))
	begin
		frame_access <= frame_access ^ 1'b1;
	end
end

always @(posedge clk)
begin
	if (reset == 1'b1)
	begin
		frame_complete_ack <= 1'b0;
	end
	else if (frame_complete_request == 1'b0)
	begin
		frame_complete_ack <= 1'b0;
	end
	else if (end_of_frame == 1'b1)
	begin
		frame_complete_ack <= 1'b1;
	end
end

always @(posedge clk)
begin
	if (reset == 1'b1)
	begin
		data_to_system <= 16'h0000;
	end
	else if (read_switch_info == 1'b1)
	begin
		data_to_system <= 16'h0000;
	end
	else if (sram_access == 1'b1)
	begin
		data_to_system <= data_from_sram;
	end
end

always @(posedge clk)
begin
	if (reset == 1'b1)
	begin
		read_switch_info <= 1'b0;
	end
	else if ((&(x_position_in)) & (&(y_position_in)))
	begin
		read_switch_info <= 1'b1;
	end
	else
	begin
		read_switch_info <= 1'b0;
	end
end

//always @(posedge clk)
//begin
//	if (reset == 1'b1)
//	begin
////		vga_ctlr_read_data <= 16'h0000;
//		data_to_vga <= 16'h0000;
//	end
//	else if (sram_access == 1'b0)
//	begin
////		if (((pixel_counter[2:1] == 2'h0) || (pixel_counter[2:1] == 2'h3) || 
////			(line_counter[2:1] == 2'h0) || (line_counter[2:1] == 2'h3)) &&
////				(x_position_in[6:0] == pixel_counter[9:3]) &&
////				(y_position_in[5:0] == line_counter[8:3]))
////		begin
////			data_to_vga <= grid_colour_in;
////		end
////		else
////		begin
//			data_to_vga <= data_from_sram;
////			vga_ctlr_read_data <= 
////				{2'b0,
////				data_from_sram[15:11], data_from_sram[15:11],
////				data_from_sram[10: 5], data_from_sram[10: 7],
////				data_from_sram[ 4: 0], data_from_sram[ 4: 0]};
////		end
//	end
//end

always @(posedge clk)
begin
	if (reset == 1'b1)
	begin
		data_to_vga	<= 16'h0000;
		for (i = PL; i >= 1; i = i - 1)
		begin
			delay_data_to_vga[i]	<= 16'h0000;
		end
	end
	else 
	begin
		data_to_vga <= delay_data_to_vga[PL];
		for (i = PL; i > 1; i = i - 1)
		begin
			delay_data_to_vga[i]	<= delay_data_to_vga[(i - 1)];
		end

		if (sram_access == 1'b0)
		begin
			delay_data_to_vga[1] <= data_from_sram;
		end
	end
end

/*****************************************************************************
 *                            Combinational logic                            *
 *****************************************************************************/


/*****************************************************************************
 *                              Internal Modules                             *
 *****************************************************************************/

Altera_UP_Avalon_SRAM Pixel_Buffer_Memory (
	// Inputs
	.clk			(clk),
	.reset			(reset),

	.address		(address_for_sram),
	.byteenable		(2'h3),
	.chipselect		(1'b1),
//	.rw				(~(sram_access & write_pixel_en)), // (1'b1), // 
	.read			(~(sram_access & write_pixel_en)), // (1'b1), // 
	.write			((sram_access & write_pixel_en)), // (1'b1), // 
	.writedata		(colour_in), // (16'h0000), // 

	// Bi-Directional
	.SRAM_DQ		(SRAM_DQ),

	// Outputs
	.SRAM_ADDR		(SRAM_ADDR),
	.SRAM_LB_N		(SRAM_LB_N),
	.SRAM_UB_N		(SRAM_UB_N),
	.SRAM_CE_N		(SRAM_CE_N),
	.SRAM_OE_N		(SRAM_OE_N),
	.SRAM_WE_N		(SRAM_WE_N),
	
	.readdata		(data_from_sram)
);

endmodule

